package uk.ac.aber.paws.server.net;

import java.io.*;
import java.net.*;
import java.util.Hashtable;
import java.util.logging.Level;

import javax.net.ssl.SSLSocket;

import uk.ac.aber.paws.client.core.Initiator;
import uk.ac.aber.paws.client.core.PAWSClient;
import uk.ac.aber.paws.client.db.DBCall;
import uk.ac.aber.paws.server.config.ConfigManager;
import uk.ac.aber.paws.server.core.PAWSServer;

/**
 * @author Rob Johnson, Aberystwyth University
 * @email rob.johnson@aber.ac.uk
 * @date 16th August 2011
 * 
 * SecureDatabaseBroker.java
 * 
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

public class SecureDatabaseBroker implements Runnable {

	private SSLSocket socket;

	public SecureDatabaseBroker(SSLSocket socket) throws SocketException { 
		   
		this.socket = socket; 
		
		// start a new thread to handle this request
		Thread t = new Thread(this); 
		t.start(); 
	    
	}
	
	public void run() { 
		
		try { 
				
			if (socket.getLocalPort() == Integer.parseInt(ConfigManager.getProperty("app.net.secureservercommsport"))) {
				DBCall dbCall = null;
				
				// read the database call info from the socket
				ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
	
				try {
					dbCall = (DBCall)ois.readObject();
				
			    
					if (dbCall != null) {
						
						if (dbCall.getPriority()) {
							dbCall.assignReplySocket(this.socket);
						}
			
						boolean success = PAWSServer.getDBRemoteCalls().addToQueue(dbCall,dbCall.getPriority());
						
						if (!dbCall.getResponseRequired()) {
							
							ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
							
							oos.writeObject(success);
							
							oos.close();
						}
					}
				}
				catch (InvalidClassException ex) {
					System.out.println("Old version detected, client:"+socket.getRemoteSocketAddress().toString());
				}
				
			}
			else if (socket.getLocalPort() == Integer.parseInt(ConfigManager.getProperty("app.net.managementcommsport"))) {
				
				ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); 
	            
				// read in the request sent to this ServerSocket
				String message = (String) ois.readObject(); 
					
				if (message.equals("MANAGEMENT_GET_DBCALL_INFO")) {
					
					ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
					
					// only if the message has been sent from the specified PAWS Server
					if (validateLocal()) {
					
						Integer data = PAWSServer.getDBRemoteCalls().getQueueSize();
						oos.writeObject(data);
					}
					
					oos.close();
				}
			}
		} 
		catch (IOException e) { 
			e.printStackTrace();         
		} 
		catch (ClassNotFoundException e) { 
			e.printStackTrace();         
		} 	    
	}
	
	/*
	 * This procedure checks if the server socket connection has come from the local host
	 * loopback adapter. This ensures that only requests sent from the same client computer are
	 * responded to.
	 * @return Returns true if the connecting socket is 127.0.0.1, false otherwise
	 */
	private boolean validateLocal() {
			
		if (this.socket.getInetAddress().getHostAddress().equals(ConfigManager.getProperty("app.main.net.loopbackaddress"))) {
			return true;
		}
		
		return false;
	}
}
